package com.yl.zqy.config;

import com.yl.zqy.common.CustomException;
import com.yl.zqy.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.yl.zqy.constant.MessageConstant.NULL_POINT_MESSAGE;

@Slf4j
@RestControllerAdvice
public class CustomExceptionAdvice {
    public static String getMessage(Throwable t) {
        StringWriter stringWriter = new StringWriter();
        t.printStackTrace(new PrintWriter(stringWriter, true));
        return stringWriter.getBuffer().toString();
    }

    @ExceptionHandler(CustomException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result<String> throwOpenException(CustomException openException) {
        //日志打印
        log.error("异常时间：" + new Date(openException.getTimestamp()) + ",异常状态码：" + openException.getCode() + "，异常信息：" + openException.getMessage());
        return Result.error(openException.getCode().intValue(), openException.getMessage());
    }

    @ExceptionHandler(value = NullPointerException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result<String> errorHandler(NullPointerException e) {
        log.error(NULL_POINT_MESSAGE, e);
        return Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), NULL_POINT_MESSAGE);
    }

    @ExceptionHandler(value = BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result<List<Map<String, Object>>> errorHandler(BindException e) {
        return Result.error(e.getBindingResult().getAllErrors()
                .stream()
                .map(t -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("rejectedMessage", t.getDefaultMessage());
                    if (t instanceof FieldError) {
                        map.put("rejectedField", ((FieldError) t).getField());
                        map.put("rejectedValue", ((FieldError) t).getRejectedValue());
                    } else {
                        map.put("rejectedMessage", t.getDefaultMessage());
                    }
                    return map;
                })
                .collect(Collectors.toList()), HttpStatus.BAD_REQUEST.value(), "请求参数校验不通过");
    }

    @ExceptionHandler(HttpMessageConversionException.class)
    public Result<String> httpMessageConversionException(HttpMessageConversionException exception) {
        //控制台输出异常
        String message = getMessage(exception);
        log.error(message);
        return Result.error("非法的请求体");
    }
}
